package calculatrice;
// ==========================================================================
//
//	- Facteur -
//
// ==========================================================================
//	<Nombre> ou (<Expression>)
// ==========================================================================

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import netg.*;
/**
 * <b>La classe Facteur </b>
 * <p>
 *	Facteur = Nombre OU Expression OU '('Expression')'
 * </p>
 * Un facteur sera soit un nombre soit une expression mais non pas les deux à la fois
 *
 * @author BOAZIZ M , BOUAYADI R , DRAMSY C , OCCELLO A , SENG D
 * @version 1.0
 *
 * @see Nombre
 * @see Expression
 *
 */
public class Facteur {
	/**
	 * Nombre du facteur
	 * @see Facteur#setN( Nombre n )
	 * @see Facteur#getN()
	 */
	private Nombre N;

	/**
	 * Expression du facteur
	 * @see Facteur#setE(Expression)
	 * @see Facteur#getE()
	 */
	private Expression E;
	/**
	 * Verifie si le Facteur est valide ou pas
	 * @see Facteur#isActif()
	 */
	boolean actif;
	/**
	 * Type du facteur
	 * si ce type = 1 alors le facteur est un nombre
	 * sinon le facteur est soit une expression soit '('Expression')'
	 *
	 * @see Facteur#setType(int)
	 * @see Facteur#getType()
	 */
	private int type;

	//constructeurs
	/**
	 * Constructeur de Facteur
	 * <p>
	 * Il créer un Facteur à partir d'un String S <br/>
	 * <u><b>si ce String a la forme d'un Nombre :</b></u><br/>
	 * ex: 123456789<br/>
	 * Il mettra type = 1 alors le facteur contiendra un nombre<br/><br/>
	 * <u><b>Sinon :</b></u><br/>
	 * ex: 1+1 OU (1+1)<br/>
	 *
	 * Il mettra type = 2  le facteur contiendra une expression<br/>
	 *
	 * </p>
	 * @param S
	 */
	public Facteur(String S){
		this.N =  null;
		this.E = null;
		this.type = 0;

		// ===============
		//System.out.println("Facteur "+S);
		//regex de prenthèses
		String regex = "^\\((.+)\\)$";
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(S);

		//regex des operateurs
		String regex2 = "\\+|\\-|\\*|\\/";
		Pattern p2 = Pattern.compile(regex2);
		Matcher m2 = p2.matcher(S);

		if( m.find())
		{
			E = new Expression(m.group(1));
			if( !E.isActif() )
			{
				actif = false;
				return;
			}
			type = 2;
		}
		else if( m2.find())
		{
			E = new Expression(S);
			if( !E.isActif() )
			{
				actif = false;
				return;
			}
			type = 2;
		}
		else
		{
			N = new Nombre(S);
			if(!N.isActif())
			{
				actif = false;
				return;
			}
			type = 1;
		}
		actif = true;
	}
	/**
	 * Constructeur de Facteur à partir d'une expression
	 * e sera affécté à E donc type sera = 2
	 *
	 * @see Facteur#E
	 *
	 * @param e
	 **/
	public Facteur( Expression e )
	{
		this.N =  null;
		this.E = e;
		this.type = 2;
	}

	/**
	 * Constructeur de Facteur à partir d'un Nombre
	 * n sera affécté à N donc type sera = 1
	 *
	 * @see Facteur#N
	 *
	 * @param n
	 **/
	public Facteur( Nombre n )
	{
		this.N =  n;
		this.E = null;
		this.type = 1;
	}

	//mutateurs
	/**
	 * Mutateur de N
	 * il affectera aussi dans cette methode type à 1
	 * @param n
	 */
	public void setN(Nombre n)
	{
		N = n;
		this.type = 1;
	}

	/**
	 * Mutateur de E
	 * il affectera aussi dans cette methode type à 2
	 * @param e
	 */
	public void setE(Expression e)
	{
		E = e;
		this.type = 2;
	}
	/**
	 * Mutateur de type
	 */
	public void setType(int type)
	{
		this.type = type;
	}

	//accesseur
	/**
	 * Accesseur de N
	 * @return N
	 */
	public Nombre getN()
	{
		return N;
	}
	/**
	 * Verifie si le Facteur est vrai ou faux
	 * @return boolean actif
	 * @see Expression#isActif()
	 * @see Nombre#isActif()
	 */
	public boolean isActif()
	{
		return actif;
	}
	/**
	 * Accesseur de E
	 * @return E
	 */
	public Expression getE()
	{
		return E;
	}

	/**
	 * Accesseur de type
	 * @return type
	 */
	public int getType()
	{
		return type;
	}

	//calcul et renvoie le nombre
	/**
	 * Calcul Le facteur en cours
	 * SI type = 1
	 * ALORS
	 * 	on retourne le calcul du nombre
	 * SINON
	 * 	on retourne le calcul de l'expression
	 *
	 * @see Expression#Calcul()
	 *
	 * @return Netg
	 */
	public Netg Calcul()
	{
		if(this.type == 0)
			return null; //1 car si on utilise operateur multiplication il ne faut pas que ca soit zero
		if(this.type == 1)
			return this.N.getV();
		return E.Calcul();
	}

}
